﻿using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration.Json;
using SqlSugar;
using SqlSugarAndEntity.Extension;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace SqlSugarAndEntity.ConfigModel
{
    public static class DataBaseConfig
    {
        /// <summary>
        /// 配置对象列表,静态实例
        /// </summary>
        private static List<ConnectionConfig> _configs = null;
        /// <summary>
        /// 获取配置的锁对象
        /// </summary>
        private static object _lockConfig = new object();
        /// <summary>
        /// 获取多租户的配置数据
        /// </summary>
        private static Dictionary<Type, object> TypeAndTenantID = null;
        /// <summary>
        /// 获取实体的多租户配置信息锁对象
        /// </summary>
        private static object _lockTypeAndTenantID=new object();
        /// <summary>
        /// 获取配置对象
        /// </summary>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        /// <exception cref="NotImplementedException"></exception>
        public static List<ConnectionConfig> GetConfig()
        {
            if (_configs == null)
            {
                lock (_lockConfig)
                {
                    if (_configs == null)
                    {
                        var _builder = new ConfigurationBuilder();
                        var config = _builder.Add(new JsonConfigurationSource { Path = "DBConfig.json", Optional = false, ReloadOnChange = true }).Build();
                        var MasterConfig = config.GetSection("TenantConfig").Get<List<ConnetionConfig>>();
                        if (MasterConfig.Count == 0)
                        {
                            throw new Exception("未读取到任何一条数据库配置信息,请检查配置文件!");
                        }
                        var Configlist = MasterConfig.Select(t =>
                        {
                            var config = new ConnectionConfig();
                            config.ConfigId = t.ConfigId;
                            config.ConnectionString = t.ConnectionString;
                            config.IsAutoCloseConnection = true;
                            switch (t.DBType)
                            {
                                case "SQLSERVER":
                                    config.DbType = DbType.SqlServer;
                                    break;
                                case "MYSQL":
                                    config.DbType = DbType.MySql;
                                    break;
                                case "ORACLE":
                                    config.DbType = DbType.Oracle;
                                    break;
                                default:
                                    throw new NotImplementedException();
                            }
                            
                            config.AopEvents = new AopEvents()
                            {
                                //执行之前
                                OnLogExecuting = (sql, p) =>
                                {
                                    Console.WriteLine(sql.LookSQL(p));
                                }
                            };
                            
                            if (t.SlaveCount > 0)
                            {
                                config.SlaveConnectionConfigs = t.SlaveConnetions.Select(s => new SlaveConnectionConfig()
                                {
                                    HitRate = s.HitRate,
                                    ConnectionString = s.ConnectionString
                                }).ToList();
                            }
                            //扩展方法
                            config.ConfigureExternalServices = new ConfigureExternalServices()
                            {
                                SqlFuncServices = CreateExternal()
                            };
                            return config;
                        })
                            .OrderBy(t => t.ConfigId)
                            .ToList();
                        _configs = Configlist;
                    }
                }
            }
            return _configs;
        }
        /// <summary>
        /// 获取多租户实体配置信息
        /// </summary>
        /// <returns></returns>
        public static Dictionary<Type, object> GetTenantInfo()
        {
            if (TypeAndTenantID == null)
            {
                lock (_lockTypeAndTenantID)
                {
                    if(TypeAndTenantID == null)
                    {
                        Assembly assembly = Assembly.Load(Assembly.GetExecutingAssembly().GetName());
                        var types = assembly.GetTypes().Where(t => !t.IsAbstract && t.GetCustomAttribute(typeof(TenantAttribute)) != null);
                        TypeAndTenantID = new Dictionary<Type, object>();
                        foreach (var type in types)
                        {
                            TypeAndTenantID.Add(type, type.GetCustomAttribute<TenantAttribute>().TypeId);
                        }
                    }
                }
            }
            return TypeAndTenantID;
        }



        private static List<SqlFuncExternal> CreateExternal()
        {
            var expMethods = new List<SqlFuncExternal>();
            #region group_concat方法
            SqlFuncExternal GroupConcat = new SqlFuncExternal()
            {
                UniqueMethodName = "GroupConcat",
                MethodValue = (expInfo, dbType, expContext) =>
                {
                    if (dbType == DbType.MySql)
                    {
                        if (expInfo.Args.Count == 1)
                        {
                            return string.Format("group_concat({0})", expInfo.Args[0].MemberName);
                        }
                        else
                        {
                            throw new Exception("未实现");
                        }
                    }
                    else if (dbType == DbType.SqlServer)
                    {
                        if (expInfo.Args.Count == 1)
                        {
                            return string.Format("string_agg({0},',')", expInfo.Args[0].MemberName);
                        }
                        else
                        {
                            throw new Exception("未实现");
                        }
                    }
                    else if (dbType == DbType.Oracle)
                    {
                        if (expInfo.Args.Count == 1)
                        {
                            return string.Format("wm_concat({0})", expInfo.Args[0].MemberName);
                        }
                        else
                        {
                            throw new Exception("未实现");
                        }
                    }
                    else
                    {
                        throw new Exception("未实现");
                    }
                       
                }
            };
            expMethods.Add(GroupConcat);
            return expMethods;
            #endregion
        }
    }
}
